﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SCMS.Model;
using SCMS.Utils.DTOs;
using System.Data.Entity;

namespace SCMS.CoreBusinessLogic._Inventory
{
    public class InventoryService : IInventoryService
    {
        private GeneralService generalObj;
        private _Item.ItemService itemObj;
        private _GoodsReceivedNote.GoodsReceivedNoteService grnObj;

        public InventoryService()
        {
            generalObj = new GeneralService();
            itemObj = new _Item.ItemService();
        }

        public List<Model.Inventory> GetInventoryList(Guid cpId, Guid? itemId = null, Guid? warehouseId = null, string categoryCode = null)
        {
            using (var dbContext = new SCMSEntities())
            {
                List<Model.Inventory> InList;
                if (itemId != null & categoryCode != null & warehouseId != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.Item.ItemCategory.CategoryCode == categoryCode & p.ItemId == itemId & p.CountryProgrammeId == cpId).ToList();
                else if (itemId != null & categoryCode != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.ItemId == itemId & p.CountryProgrammeId == cpId & p.Item.ItemCategory.CategoryCode == categoryCode).ToList();
                else if (itemId != null & warehouseId != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.ItemId == itemId & p.CountryProgrammeId == cpId & p.WareHouseId == warehouseId).ToList();
                else if (itemId != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.ItemId == itemId & p.CountryProgrammeId == cpId).ToList();
                else if (warehouseId != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.WareHouseId == warehouseId & p.CountryProgrammeId == cpId).ToList();
                else if (categoryCode != null)
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.Item.ItemCategory.CategoryCode == categoryCode & p.CountryProgrammeId == cpId).ToList();
                else
                    InList = dbContext.Inventories.Include("Item").Include("WareHouse").Include("Item.ItemClassification").Include("Item.ItemCategory").Include("Item.UnitOfMeasure").Where(p => p.CountryProgrammeId == cpId).ToList();
                //foreach (Inventory item in InList)
                //{
                //    Model.Item it = item.Item;
                //    Model.UnitOfMeasure u = it.UnitOfMeasure;
                //    Model.ItemCategory itc = it.ItemCategory;
                //    Model.ItemClassification itk = it.ItemClassification;
                //    Model.WareHouse wh = item.WareHouse;
                //}
                return InList;
            }
        }

        public long GetItemExistingTotalQty(Guid itemId)
        {
            using (var db = new SCMSEntities())
            {
                return db.Inventories.Where(p => p.ItemId == itemId).Sum(p => p.Quantity);
            }
        }

        public List<Model.Asset> GetAssetInventoryList(Guid cpId, Guid? AssetId = null, Guid? ItemId = null, Guid? warehouseId = null)
        {
            using (var dbContext = new SCMSEntities())
            {
                List<Model.Asset> astList;
                if (ItemId != null && warehouseId != null)
                    astList = dbContext.Assets
               .Include("Item.ItemClassification")
               .Include("ProjectDonor1.Project")
               .Include("ProjectDonor1.Donor")
               .Include("WareHouse")
               .Include("Staff")
               .Include("Staff.Person")
               .Include("Currency")
               .Include("AssetManagments")
               .Include("ProjectDonor.Project")
               .Include("ProjectDonor.Donor")
               .Include("AssetManagments.ProjectDonor")
               .Where(p => p.ItemId == ItemId & p.CountryProgramId == cpId & p.CurrentWareHouseId == warehouseId & p.IsDesposed == false).ToList();
                else if (ItemId != null && warehouseId == null)
                    astList = dbContext.Assets
               .Include("Item.ItemClassification")
               .Include("ProjectDonor1.Project")
               .Include("ProjectDonor1.Donor")
               .Include("WareHouse")
               .Include("Staff")
               .Include("Staff.Person")
               .Include("Currency")
               .Include("AssetManagments")
               .Include("ProjectDonor.Project")
               .Include("ProjectDonor.Donor")
               .Include("AssetManagments.ProjectDonor")
               .Where(p => p.ItemId == ItemId & p.CountryProgramId == cpId & p.IsDesposed == false).ToList();
                else
                {
                    if (AssetId == null)
                        astList = dbContext.Assets
               .Include("Item.ItemClassification")
               .Include("ProjectDonor1.Project")
               .Include("ProjectDonor1.Donor")
               .Include("WareHouse")
               .Include("Staff")
               .Include("Staff.Person")
               .Include("Currency")
               .Include("AssetManagments")
               .Include("ProjectDonor.Project")
               .Include("ProjectDonor.Donor")
               .Include("AssetManagments.ProjectDonor")
               .Where(p => p.CountryProgramId == cpId & p.IsDesposed == false).ToList();
                    else
                        astList = dbContext.Assets
               .Include("Item.ItemClassification")
               .Include("ProjectDonor1.Project")
               .Include("ProjectDonor1.Donor")
               .Include("WareHouse")
               .Include("Staff")
               .Include("Staff.Person")
               .Include("Currency")
               .Include("AssetManagments")
               .Include("ProjectDonor.Project")
               .Include("ProjectDonor.Donor")
               .Include("AssetManagments.ProjectDonor")
               .Where(p => p.Id == AssetId & p.CountryProgramId == cpId & p.IsDesposed == false).ToList();
                }

                //foreach (Asset item in astList)
                //{
                //    //Model.Item it = item.Item;
                //    //foreach (AssetManagment astmgt in item.AssetManagments)
                //    //{ Model.AssetManagment astgt = astmgt; if (astmgt.currentProjectId != null) { Model.ProjectDonor pd = astmgt.ProjectDonor; } }
                //    //Model.ItemClassification itk = it.ItemClassification;
                //    //Model.Project pro = item.ProjectDonor1.Project;
                //    //Model.Donor donor = item.ProjectDonor1.Donor;
                //    //Model.WareHouse wh = item.WareHouse;
                //    Model.ProjectDonor kk = item.ProjectDonor;
                //    Model.Staff s = item.Staff;
                //    Model.Currency c = item.Currency;
                //    if (s != null) { Model.Person p = s.Person; }
                //}
                return astList;
            }
        }

        public bool IsAssetEdited(Model.Asset entity)
        {
            using (var db = new SCMSEntities())
            {
                if (entity.IsFleet)
                    if (db.FleetDetails.FirstOrDefault(p => p.AssetId == entity.Id) == null)
                        db.FleetDetails.AddObject(new FleetDetail() { Id = Guid.NewGuid(), CountryProgrammeId = entity.CountryProgramId, AssetId = entity.Id, IssueDate = DateTime.Now });
                db.Assets.Attach(entity);
                db.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
                return (db.SaveChanges() > 0) ? true : false;
            }
        }

        public List<Model.Asset> GetAssetList(Guid cpId)
        {
            using (var db = new SCMSEntities())
            {
                return db.Assets.Where(p => p.CountryProgramId == cpId & p.IsDesposed == false).OrderBy(a => a.Name).ToList();
            }
        }

        public List<Model.Asset> GetAssetList(Guid cpId, bool isFleet, bool returnUnregisteredFleetAsset)
        {
            using (var db = new SCMSEntities())
            {
                if (!returnUnregisteredFleetAsset)
                    return db.Assets.Where(p => p.CountryProgramId == cpId & p.IsFleet == isFleet & p.IsDesposed == false).OrderBy(a => a.Name).ToList();

                var query = from asst in db.Assets
                            where asst.CountryProgramId == cpId & asst.IsFleet == true & asst.IsDesposed == false &
                            !(from flit in db.FleetDetails
                              select flit.AssetId).Contains(asst.Id)
                            select asst;

                return query.ToList<Model.Asset>();
            }
        }

        public List<Model.Asset> GetAssetList(Guid cpId, string assetName)
        {
            using (var db = new SCMSEntities())
            {
                return db.Assets.Where(p => p.CountryProgramId == cpId & p.IsDesposed == false & p.Name.ToLower().Equals(assetName.ToLower())).OrderBy(a => a.Name).ToList();
            }
        }

        public List<Depreciation> GetAnnualDepreciation(Guid assetId)
        {
            using (var db = new SCMSEntities())
            {
                var depList = db.Depreciations.Include("Asset.Currency").Where(p => p.Period % 12 == 0 && p.AssetId == assetId).OrderBy(p => p.Period).ToList();
                //foreach (var dep in depList)
                //{
                //    var curr = dep.Asset.Currency;
                //}
                return depList;
            }
        }

        public List<Depreciation> GetDetailedDepreciation(Guid annualYearId)
        {
            using (var db = new SCMSEntities())
            {
                Model.Depreciation deprentity = db.Depreciations.FirstOrDefault(p => p.Id == annualYearId);
                DateTime statdate = deprentity.Date.AddMonths(-11);
                return db.Depreciations.Where(p => p.Date >= statdate && p.Date <= deprentity.Date && p.AssetId == deprentity.AssetId).OrderBy(p => p.Period).ToList();
            }
        }

        public Asset GetAssetById(Guid id)
        {
            using (var context = new SCMSEntities())
            {
                return context.Assets.FirstOrDefault(a => a.Id == id);
            }
        }

        public string GetAssetCurrentProjetNoByAssetId(Guid assetId)
        {
            using (var db = new SCMSEntities())
            {

                Model.Asset aset = db.Assets.FirstOrDefault(p => p.Id == assetId);
                if (!aset.IsAssetStateChanged) return aset.ProjectDonor.ProjectNumber;
                else
                {
                    Model.AssetManagment asetmgt = db.AssetManagments.Where(p => p.AssetId == assetId).OrderByDescending(p => p.IssueDate).FirstOrDefault();
                    if (asetmgt.currentProjectId != null) return asetmgt.ProjectDonor.ProjectNumber;
                    else return asetmgt.PartnerName;
                }
            }
        }

        public List<GeneralInventorySummary> Find(List<Guid> ids)
        {
            List<GeneralInventorySummary> invs = new List<GeneralInventorySummary>();

            using (var context = new SCMSEntities())
            {
                var results = from myInventory in context.Inventories
                              where ids.Contains(myInventory.Id)
                              select myInventory;

                foreach (Model.Inventory item in results.ToList())
                {
                    GeneralInventorySummary tmp = new GeneralInventorySummary();
                    tmp.Id = item.Id;
                    tmp.Classification = item.Item.ItemClassification.Name;
                    tmp.ItemName = item.Item.Name;
                    tmp.Category = item.Item.ItemCategory.CategoryName;
                    tmp.Quantity = item.Quantity;

                    invs.Add(tmp);
                }

            }

            return invs;

        }

    }

}
